﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Animation;
using MapLibrary;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework.Content;

namespace AI
{
    public class Bot
    {
        public Sprite Owner { get; set; }
        protected Vector2 tVec;
        protected float Max_X_Velocity = ConvertUnits.ToSimUnits(300);
        protected float Max_Y_Velocity = ConvertUnits.ToSimUnits(300);

        public Bot(Sprite owner)
        {
            Owner = owner;
            tVec = new Vector2();
        }

        public Bot()
        {
            tVec = new Vector2();
        }

        public virtual void Init(GameWorld world, ContentManager cm)
        {

        }

        public virtual void Update(Level level, World world)
        {

        }

        public virtual void OnRemove(World world)
        {

        }

        public virtual void ClampVelocity(float maxX, float maxY)
        {
            /*Vector2 v = Owner.Body.LinearVelocity;

            v.X = (v.X > maxX) ? maxX : v.X;
            v.X = (v.X < -maxX) ? -maxX : v.X;

            v.Y = (v.Y > maxY) ? maxY : v.Y;
            v.Y = (v.Y < -maxY) ? -maxY : v.Y;

            
            Owner.Body.LinearVelocity = v;*/
        }

        protected float DistanceFromFloor()
        {
            Vector2 rayCastStart = Owner.Body.Position;
            Vector2 rayCastEnd = Owner.Body.Position + 5 * new Vector2(0, ConvertUnits.ToSimUnits(Owner.Type.Height));

            float fractionDist = 0.0f;
            Owner.World.PhysicsWorld.RayCast((fixture, point, normal, fraction) =>
                {
                    fractionDist = fraction;
                    return fraction;
                }, rayCastStart, rayCastEnd);

            return Vector2.Distance(rayCastStart, rayCastEnd) * fractionDist * 1.2f;
        }

        protected float DistanceFromWall(bool left)
        {
            int x = (left) ? -1 : 1;

            Vector2 rayCastStart = Owner.Body.Position;
            Vector2 rayCastEnd = Owner.Body.Position + 5 * x * new Vector2(ConvertUnits.ToSimUnits(Owner.Type.Width), 0);

            float fractionDist = 0.0f;
            Owner.World.PhysicsWorld.RayCast((fixture, point, normal, fraction) =>
            {
                fractionDist = fraction;
                return fraction;
            }, rayCastStart, rayCastEnd);

            return Vector2.Distance(rayCastStart, rayCastEnd) * fractionDist * 1.2f;
        }

        /// <summary>
        /// Returns whether or not the Bot is near the left edge.  We say that it is
        /// near if it is at most <i>buffer</i> away from the edge in the x direction.
        /// </summary>
        /// <param name="bufferSize"></param>
        /// <returns></returns>
        protected bool NearLedgeLeft(float bufferSize)
        {
            float temp = DistanceFromFloor();
            float y = DistanceFromFloor();//2.0f * ConvertUnits.ToSimUnits(Owner.Type.Height); //approximation of the height of the sprite

            Vector2 rayCastStart = Owner.Body.Position;
            Vector2 rayCastEnd = rayCastStart + new Vector2(-bufferSize, y);

            bool near = true;

            Owner.World.PhysicsWorld.RayCast((fixture, point, normal, fraction) =>
            {
                LevelCollisionRegion levelRegion = fixture.Body.UserData as LevelCollisionRegion;
                if (levelRegion != null)
                {
                    if (fraction < .85)
                        near = false;
                    else
                        near = true;

                    return fraction;
                }
                else
                {
                    return -1;
                }
            }, rayCastStart, rayCastEnd);

            return near;
        }

        protected bool NearLedgeRight(float bufferSize)
        {
            float y = DistanceFromFloor();//2.0f * ConvertUnits.ToSimUnits(Owner.Type.Height); //approximation to the height of the sprite

            Vector2 rayCastStart = Owner.Body.Position;
            Vector2 rayCastEnd = rayCastStart + new Vector2(bufferSize + ConvertUnits.ToSimUnits(Owner.Type.Width), y);  //dirty fix, since the sprite pos is at the top left corner

            bool near = true;

            Owner.World.PhysicsWorld.RayCast((fixture, point, normal, fraction) =>
            {
                LevelCollisionRegion levelRegion = fixture.Body.UserData as LevelCollisionRegion;
                if (levelRegion != null)
                {
                    if (fraction < .85f)
                        near = false;
                    else
                        near = true;

                    return fraction;
                }
                else
                {
                    return -1;
                }
            }, rayCastStart, rayCastEnd);

            return near;
        }
    }
}
